home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Three-dimensional Fractal Contour Map generator.
- ** Program originally in MicroSoft BASIC for the Macintosh.
- ** Taken from July 1985 Creative Computing.
- **
- ** Used as an example BASIC-C comparison.
- */
-
- #include <memory.h>
- #include <quickdraw.h>
- #include <font.h>
- #include <window.h>
- #include <osutil.h>
- #include <menu.h>
- #include <event.h>
- #include <textedit.h>
- #include <dialog.h>
- #include <desk.h>
- #include <control.h>
- #include <toolutil.h>
- #define watchCursor 4 /* Should be in TOOLUTIL.H but isn't. JEC */
- #include <resource.h>
- #include <stdio.h>
-
- #include "fractal.h"
-
- GrafPtr screenport; /* A port for the whole screen. */
- WindowPtr mywindow; /* Our one window. */
- WindowRecord wrecord; /* Storage for window record. */
- MenuHandle mymenus[LASTMENU + 1]; /* Our menus. */
- PicHandle thepicture;
- BitMap savepix; /* Storage for the update bitmap. */
-
- EventRecord myevent;
- WindowPtr whichwindow; /* Points to window of MouseDown. */
- int windowcode; /* What mouse was in when event posted. */
- Boolean userdone; /* True when user wants to exit program. */
- int ispicture; /* True if there is a Picture definition of the
- contour available. */
- int isbitmap; /* True if there is a bitmap copy of the contour
- available. Saves time in update events. */
- int usebitmap; /* True if the bitmap should be used to update. */
-
- main() {
- setup();
- maineventloop();
- }
-
- /*############################ MainEventLoop ########################*/
-
- maineventloop() {
-
- FlushEvents(everyEvent, 0);/* discard leftover events */
-
- /* get next event, and handle it appropriately, until user QUITs */
-
- userdone = 0;
- do {
- SystemTask(); /* Handle desk accessories. */
- if (GetNextEvent(everyEvent, &myevent)) {
- /* get event; if for us... */
- switch (myevent.what) {/* handle each kind of event */
- case mouseDown: /* find out what window the mouse went
- down in, and where in it */
- windowcode = FindWindow(pass(myevent.where), &whichwindow);
- switch (windowcode) {
- /* handle mouse-down for each place */
- case inSysWindow:
- /* handle the desk accessories */
- SystemClick(&myevent, whichwindow);
- break;/* insyswindow */
- case inMenuBar: /* handle the command */
- userdone = docommand(MenuSelect(&myevent.where));
- break;/* inmenubar */
- case inDrag: /* No Drag Region, treat as Content. */
- case inContent:
- /* includes inGrow if window inactive.
- Activate window */
- if (whichwindow == mywindow)
- /* make sure it's for mine */
- if (whichwindow != FrontWindow())
- SelectWindow(whichwindow);
- /* make it active */
- break;
- case inGrow: /* No Grow Region */
- break;
- case inGoAway:
- /* we don't have a GoAway region */
- break;
- }
- break; /* switch */
-
- case keyDown:
- case autoKey: /* if command key, pass the char to
- MenuKey */
- if ((myevent.modifiers & cmdKey) != 0)
- userdone = docommand(MenuKey((char) (myevent.message & charCodeMask)));
- case updateEvt: /* if it's for our window, update it */
- if ((WindowPtr) (myevent.message) == mywindow)
- updatewindow(mywindow);
- /* redraw the window contents */
- break;
- case activateEvt:
- /* if for our window, set port as nec. */
- if ((WindowPtr) (myevent.message) == mywindow) {
- /* my window */
- if (myevent.modifiers & 1) {
- /* odd means an activate event */
- SetPort(mywindow);
- /* activate evt: work in our own port */
- DisableItem(mymenus[EDITMENU], 0);
- EnableItem(mymenus[FILEMENU], 0);
- EnableItem(mymenus[SETUPMENU], 0);
- DrawMenuBar();
- }
- else {
- SetPort(screenport);
- /* deactivate evt: our port is gone; keep
- port from dangling */
- EnableItem(mymenus[EDITMENU], 0);
- DisableItem(mymenus[FILEMENU], 0);
- DisableItem(mymenus[SETUPMENU], 0);
- DrawMenuBar();
- }
- } break;
- }
- }
-
- } while (userdone == 0);
- }
-
- /*
- handle a command given through a menu selection
- ############################ DoCommand ##############################
-
- We carry out the command indicated by mResult.
- If it was Quit, we return true, else false. Since the menu was
- highlighted by MenuSelect, we must finish by unhighlighting it
- to indicate we're done.
- */
- int docommand(mresult)
- long mresult;
- {
- int refnum;
- int themenu,
- theitem;
- char name[255];
- GrafPtr saveport; /* for saving current port in when opening
- a desk accessory */
- int returns;
-
- returns = 0; /* assume Quit not selected */
- themenu = HiWord(mresult); /* get the menu selected */
- theitem = LoWord(mresult); /* ... and the item of that menu */
- switch (themenu) {
- case 0:
- break; /* user made no selection; do nothing */
-
- case APPLEMENU:
-
- if (theitem == 1) /* Tell about FracCont */
- report();
- else { /* run a desk accessory; make sure port is
- preserved */
- GetPort(&saveport);
- GetItem(mymenus[APPLEMENU], theitem, name);
- /* get name */
- refnum = OpenDeskAcc(name);/* run the desk accessory */
- SetPort(saveport);
- }
- break;
-
- case FILEMENU:
- switch (theitem) {
- case ANOTHER: /* New Surface */
- calcsurf(contlevl);
- InvalRect(&mywindow -> portRect);
- usebitmap = FALSE;
- break;
- case SAVEPAINT: /* Not yet. */
- break;
- case IQUIT:
- returns = 1;/* Quit */
- break;
- } /* FILEMENU case */
- break;
-
- case SETUPMENU:
- switch (theitem) {
- case SETUP: /* Setup */
- setupDlg();
- break;
- } /* SETUPMENU case */
-
- } /* menu case */
-
- HiliteMenu(0); /* turn off hilighting on the menu just
- used */
- return (returns);
- } /* DoCommand */
-
- /*############################ Setup Dialog ######################*/
-
- TerrainBTN(ptr, oncontrl, offcontrl)
- DialogPtr ptr;
- int oncontrl, offcontrl;
- {
- int itemtype;
- ControlHandle item;
- Rect itembox;
-
- GetDItem(ptr, offcontrl, &itemtype, &item, &itembox);
- SetCtlVal(item, 0); /* Turn off old Default Button. */
- GetDItem(ptr, oncontrl, &itemtype, &item, &itembox);
- SetCtlVal(item, 1); /* Turn on Default Button. */
- return oncontrl;
- }
-
- setupDlg() /* Do the SETUP menu dialog. */
- {
- int newtype; /* Selected Contour type. */
- int newlevel; /* Selected Level of Detail. */
- int userexit;
- int doanother; /* True if we need to recalc. */
- int itemhit; /* Item # of punched button (or whatever) */
- DialogPtr setupptr;
- char asciibufr[10];
- int itemtype;
- ControlHandle item;
- Rect itembox;
-
- newtype = conttype; /* SETUPMTN, SETUPHIL, or SETUPWATR */
- newlevel = contlevl;
- doanother = FALSE;
-
- setupptr = GetNewDialog(STPDLGID, NULL, (long) -1);
- TerrainBTN(setupptr, conttype, conttype);
- asciibufr[1] = newlevel + '0'; /* Only good for 0..9, OK here. */
- asciibufr[0] = 1;
- GetDItem(setupptr, SETUPLEVL, &itemtype, &item, &itembox);
- SetIText(item, asciibufr);
- SelIText(setupptr, SETUPLEVL, 0, 100); /* Hilite text field. */
- userexit = FALSE;
- do {
- ModalDialog(NULL, &itemhit);
- /* carry out dialog; NIL => no FilterProc;
- return item Hit when done */
- GetDItem(setupptr, SETUPLEVL, &itemtype, &item, &itembox);
- GetIText(item, asciibufr); /* Get Level field */
- if (asciibufr[0] != 1) /* Only good for 1..9, OK here. */
- newlevel = 100;
- else
- newlevel = asciibufr[1] - '0';
- if (newlevel < 1 || newlevel > MAXLEVEL)
- SelIText(setupptr, SETUPLEVL, 0, 100); /* Hilite text field. */
- if (itemhit == SETUPMTN)
- newtype = TerrainBTN(setupptr, itemhit, newtype);
- if (itemhit == SETUPHIL)
- newtype = TerrainBTN(setupptr, itemhit, newtype);
- if (itemhit == SETUPWATR)
- newtype = TerrainBTN(setupptr, itemhit, newtype);
- if (itemhit == SETUPOK && ((newlevel > 0) & (newlevel <= MAXLEVEL))) {
- if (conttype != newtype || contlevl != newlevel) {
- if (contlevl != newlevel)
- doanother = TRUE;
- InvalRect(&mywindow -> portRect);
- usebitmap = FALSE;
- }
- contlevl = newlevel;
- conttype = newtype;
- userexit = TRUE;
- }
- if (itemhit == SETUPCAN)
- userexit = TRUE;
- } while (!userexit);
- DisposDialog(setupptr); /* release storage and remove dialog from
- screen */
- if (doanother)
- calcsurf(newlevel); /* Removes dialog first. */
- } /* Setup */
-
-
- /*
- ############################ Report #################################
- */
-
- report()
- {
- int itemhit;
- DialogPtr reportptr;
-
- reportptr = GetNewDialog(INFOSCR1, NULL, (long) -1);
- /* Get from Resource file; NIL => use heap
- storage; -1 => make dlg frontmost */
-
- ModalDialog(NULL, &itemhit);
- /* carry out dialog; NIL => no FilterProc;
- return item Hit when done */
- DisposDialog(reportptr); /* release storage and remove dialog from
- screen */
- if (itemhit == INFOMORE) {
- reportptr = GetNewDialog(INFOSCR2, NULL, (long) -1);
- ModalDialog(NULL, &itemhit);
- DisposDialog(reportptr);
- }
- }
-
-
- /*
-
- SetUps for handling memory
- ########################## SetUpMemory ############################
- */
-
- setupmemory() {
-
-
- #define maxStackSize 8192 /* max size of stack; the heap gets the
- rest */
-
- typedef long *lomemptr; /* a pointer to low memory locations */
-
- lomemptr nilptr; /* will have value NIL */
- lomemptr stackbaseptr; /* points to current stack base */
-
- /*
- If you define a GrowZone function to handle bad memory problems,
- you should define it at the top level (not nested), and set it
- here. We don't.
- */
- /* SetGrowZone(&mygrowzone); */
-
- /*
- Place a longint -1 (an odd and therefore illegal address) in the
- memory location that would be referenced by an accidentally-NULL
- handle, so the error will be caught at handle-reference time (as
- an Address error, ID=02) instead of later on.
- */
-
- nilptr = NULL;
- *nilptr = -1;
-
- /*
- If you needed to use an Application heap limit other than the
- default (which allows 8K for the stack), you'd set it here,
- possible using this technique of explicitly specifying the maximum
- stack size and allocating the rest to the heap. Should be
- independent of memory size. */
-
- stackbaseptr = (lomemptr) 0x908;
- /* CurStackBase from Tlasm/sysequ.text */
- SetApplLimit((Ptr) (*stackbaseptr - maxStackSize));
-
- /*
- Expand the application heap zone to its maximum size, without
- purging any purgeable resources. This saves memory compactions
- and heap expansions later.
- */
-
- MaxApplZone();
-
- /*
- get plenty of master pointers now; if we let the Memory Manager
- allocate them as needed, they'd form non-relocatable islands in
- the heap.
- */
-
- MoreMasters();
- MoreMasters();
-
- } /* SetUpMemory */
-
- /*
- ############################ SetUpMenus #############################
- Once-only initialization for menus
- We read in all menus from the resource file, and install them,
- and all desk accessories (drivers).
- */
-
- setupmenus() {
- int i;
- for (i = 1; i <= LASTMENU; i++)/* get all my menus in */
- mymenus[i] = GetMenu(i);/* use the fact that our menu ID's start
- at 1 */
- AddResMenu(mymenus[APPLEMENU], 'DRVR');
- /* pull in all desk accessories */
- for (i = 1; i <= LASTMENU; i++)
- InsertMenu(mymenus[i], 0);/* insert menus; 0 => put at end */
- DrawMenuBar();
- }
-
- /*
-
- body of SetUp
- Once-only initialization.
- ############################ SetUp ##############################
-
- Initialize our program. It seems best to handle:
- Memory inits first, ToolBox inits second, then the program variables'
- inits. Note that the order of inits is important; see "Using the
- Dialog Manager" in the Dialog Mgr section.
-
- */
-
- setup() {
-
- char *ctop();
-
- setupmemory(); /* init memory layout and protection */
-
- /* init QuickDraw, and everybody else */
-
- InitGraf(&thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(NULL); /* NULL => no Restart proc; see Dialog Mgr
- and System Error Handler */
- InitCursor();
-
- /*
- Init the system event mask, in case the previous program left
- it in a bad state. If you set it non-standard here, FIX IT
- BEFORE EXITING, because the Finder (1.1g) does NOT set it.
- */
- SetEventMask(everyEvent - keyUpMask);/* standard setting */
- /*
- Get the port which is the whole screen, to use when deactivating
- our window. This prevents the current grafPort pointer from
- ever dangling.
- */
- GetWMgrPort(&screenport); /* get whole screen port that window mgr
- uses */
- SetPort(screenport); /* and start off with it */
-
- /*
- get window: use wRecord storage. Port is set to that of the
- new window.
- GetNewWindow posts an update event for the new window,
- so it will be redrawn right away.
- */
- #ifdef DEVELOP
- OpenResFile(ctop(DEVELOP));
- #endif
- mywindow = GetNewWindow(WINDOWID, &wrecord, (long) -1);
- /* -1 => frontmost window */
-
- /* pull in and set up our menus */
- setupmenus();
- CouldDialog(STPDLGID); /* Preload the Setup Dialog. */
-
- conttype = DEFLTTYP; /* Default style */
- contlevl = DEFLTLEV; /* Default Level */
- isbitmap = FALSE;
- /* Allocate the data array. */
- points = NewPtr((long) XDIM*YDIM*(sizeof(int))); /* Non-reloc, but so what. */
- calcsurf(contlevl); /* Do at least one first. */
- }
-
- /*
-
- Update the contents of the given window
- ############################ UpdateWindow ##########################
-
- This is our response to receipt of an update event for myWindow.
- Since the window is likely to be inactive, the current grafPort
- will be elsewhere. We must change it for drawing, yet leave it
- as it was.
- */
-
- updatewindow(awindow)
- WindowPtr awindow;
- {
- GrafPtr saveport; /* to save and restore the old port */
-
- BeginUpdate(awindow); /* reset ClipRgn etc to only redraw what's
- necessary. */
-
- GetPort(&saveport); /* don't trash the port; we might be
- updating an inactive window */
- SetPort(awindow); /* work in the specified window */
-
- drawwindow(); /* redraw contents of window */
-
- SetPort(saveport); /* all nice and tidy as before */
-
- EndUpdate(awindow);
-
- } /* UpdateWindow */
-
- /*
- Redraw my window
- ############################ DrawWindow #############################
-
- We draw all the contents of our one window, myWindow.
- */
-
- drawwindow()
- {
- /* Possibly save the drawing contents in a picture. This will allow
- much faster update events than calling plotdata() repeatedly.
- This is only to speed up Desk Accessory movement and the
- re-painting after the Options Dialog is removed. */
- CursHandle ticktock;
-
- ticktock = GetCursor(watchCursor);
- if (ticktock)
- SetCursor(*ticktock); /* Show watch (wait) */
- if (usebitmap) {
- CopyBits(&savepix, &mywindow->portBits,
- &savepix.bounds, &mywindow->portRect,
- srcCopy, 0L);
- }
- else {
- if (isbitmap)
- DisposPtr(savepix.baseAddr);
- savepix.bounds.top = mywindow->portRect.top;
- savepix.bounds.bottom = mywindow->portRect.bottom;
- savepix.bounds.left = mywindow->portRect.left;
- savepix.bounds.right = mywindow->portRect.right;
- savepix.rowBytes = mywindow->portBits.rowBytes;
- savepix.baseAddr = NewPtr((long) savepix.rowBytes *
- (savepix.bounds.bottom - savepix.bounds.top));
- EraseRect(&mywindow->portRect);
- plotdata();
- CopyBits(&mywindow->portBits, &savepix,
- &mywindow->portRect, &savepix.bounds,
- srcCopy, 0L);
- isbitmap = usebitmap = TRUE;
- }
- #ifdef not_defined
- if (ispicture)
- KillPicture(thepicture);
- thepicture = OpenPicture(&mywindow -> portRect);
- ShowPen(); /* We want the picture shown while being drawn. */
- EraseRect(&mywindow -> portRect);
- plotdata();
- HidePen(); /* Balance the ShowPen() above. */
- ClosePicture();
- ispicture = TRUE;
- #endif
- InitCursor();
- } /* DrawWindow */
-
- /*
- * The following routine was used while debugging and testing the program.
- * The routine is called just like "printf()", but the output is
- * directed to the printer port. Use -7 for the modem port. The
- * port must already be opened. Use MIXCROOT and do a 2> .b(a)out
- * to easily do this.
- */
-
- #ifdef DEBUG
- debug(fmt, arg)
- char *fmt;
- unsigned arg;
- {
- int put();
-
- format(put, fmt, &arg);
- }
-
- put(c)
- char c;
- {
- long i;
-
- i = 1;
- if (c=='\n')
- put('\r');
- FSWrite(DEBUG, &i, &c);
- if (c=='\n')
- for (i=2000; i; i--)
- ;
- }
- #endif
-
-